<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.3">
<title>Contracts Representing Scenarios (Stateful Stubs) 2.1.3.BUILD-SNAPSHOT</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
/* Remove comment around @import statement below when using as a custom stylesheet */
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
audio,canvas,video{display:inline-block}
audio:not([controls]){display:none;height:0}
[hidden],template{display:none}
script{display:none!important}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
body{margin:0}
a{background:transparent}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
abbr[title]{border-bottom:1px dotted}
b,strong{font-weight:bold}
dfn{font-style:italic}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
body{-webkit-font-smoothing:antialiased}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.center{margin-left:auto;margin-right:auto}
.spread{width:100%}
p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:none}
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.no-bullet{list-style:none}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
abbr{text-transform:none}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
blockquote cite:before{content:"\2014 \0020"}
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
table thead,table tfoot{background:#f7f8f7;font-weight:bold}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
body{tab-size:4}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}
.clearfix:after,.float-group:after{clear:both}
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menu{color:rgba(0,0,0,.8)}
b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}
b.button:before{content:"[";padding:0 3px 0 2px}
b.button:after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}
#header:after,#content:after,#footnotes:after,#footer:after{clear:both}
#content{margin-top:1.25em}
#content:before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span:before{content:"\00a0\2013\00a0"}
#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark:before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber:after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media only screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
.sect1{padding-bottom:.625em}
@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}
.sect1+.sect1{border-top:1px solid #efefed}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}
.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}
table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.listingblock>.content{position:relative}
.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
.listingblock:hover code[data-lang]:before{display:block}
.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}
.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
table.pyhltable td.code{padding-left:.75em;padding-right:0}
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
pre.pygments .lineno{display:inline-block;margin-right:.25em}
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
.quoteblock .quoteblock blockquote:before{display:none}
.verseblock{margin:0 1em 1.25em 1em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract{margin:0 0 1.25em 0;display:block}
.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}
.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}
table.tableblock{max-width:100%;border-collapse:separate}
table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot{border-width:1px 0}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
td>div.verse{white-space:pre}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none}
ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em}
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em}
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px}
ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}
ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}
ul.inline>li>*{display:block}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist>table tr>td:first-of-type{padding:0 .75em;line-height:1}
.colist>table tr>td:last-of-type{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
.gist .file-data>table td.line-data{width:99%}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background-color:#00fafa}
.black{color:#000}
.black-background{background-color:#000}
.blue{color:#0000bf}
.blue-background{background-color:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background-color:#fa00fa}
.gray{color:#606060}
.gray-background{background-color:#7d7d7d}
.green{color:#006000}
.green-background{background-color:#007d00}
.lime{color:#00bf00}
.lime-background{background-color:#00fa00}
.maroon{color:#600000}
.maroon-background{background-color:#7d0000}
.navy{color:#000060}
.navy-background{background-color:#00007d}
.olive{color:#606000}
.olive-background{background-color:#7d7d00}
.purple{color:#600060}
.purple-background{background-color:#7d007d}
.red{color:#bf0000}
.red-background{background-color:#fa0000}
.silver{color:#909090}
.silver-background{background-color:#bcbcbc}
.teal{color:#006060}
.teal-background{background-color:#007d7d}
.white{color:#bfbfbf}
.white-background{background-color:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background-color:#fafa00}
span.icon>.fa{cursor:default}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]:after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@media print{@page{margin:1.25cm .75cm}
*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]:after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
.sect1{padding-bottom:0!important}
.sect1+.sect1{border:0!important}
#header>h1:first-child{margin-top:1.25rem}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span:before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]:before{display:block}
#footer{background:none!important;padding:0 .9375em}
#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
</style>
<style>
.hidden {
	display: none;
}

.switch {
	border-width: 1px 1px 0 1px;
	border-style: solid;
	border-color: #7a2518;
	display: inline-block;
}

.switch--item {
	padding: 10px;
	background-color: #ffffff;
	color: #7a2518;
	display: inline-block;
	cursor: pointer;
}

.switch--item.selected {
	background-color: #7a2519;
	color: #ffffff;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
<script type="text/javascript">
function addBlockSwitches() {
	$('.primary').each(function() {
		primary = $(this);
		createSwitchItem(primary, createBlockSwitch(primary)).item.addClass("selected");
		primary.children('.title').remove();
	});
	$('.secondary').each(function(idx, node) {
		secondary = $(node);
		primary = findPrimary(secondary);
		switchItem = createSwitchItem(secondary, primary.children('.switch'));
		switchItem.content.addClass('hidden');
		findPrimary(secondary).append(switchItem.content);
		secondary.remove();
	});
}

function createBlockSwitch(primary) {
	blockSwitch = $('<div class="switch"></div>');
	primary.prepend(blockSwitch);
	return blockSwitch;
}

function findPrimary(secondary) {
	candidate = secondary.prev();
	while (!candidate.is('.primary')) {
		candidate = candidate.prev();
	}
	return candidate;
}

function createSwitchItem(block, blockSwitch) {
	blockName = block.children('.title').text();
	content = block.children('.content').first().append(block.next('.colist'));
	item = $('<div class="switch--item">' + blockName + '</div>');
	item.on('click', '', content, function(e) {
		$(this).addClass('selected');
		$(this).siblings().removeClass('selected');
		e.data.siblings('.content').addClass('hidden');
		e.data.removeClass('hidden');
	});
	blockSwitch.append(item);
	return {'item': item, 'content': content};
}

$(addBlockSwitches);
</script>
</head>

<body class="article toc2 toc-left">
<div id="header">
<h1>Contracts Representing Scenarios (Stateful Stubs) 2.1.3.BUILD-SNAPSHOT</h1>
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_scenarios">Scenarios</a></li>
<li><a href="#_flow">Flow</a></li>
<li><a href="#_tutorial">Tutorial</a>
<ul class="sectlevel3">
<li><a href="#_ide_setup">IDE setup</a></li>
<li><a href="#_cloning_the_producer_s_code">Cloning the producer&#8217;s code</a></li>
<li><a href="#_adding_dependencies_in_the_producer_s_clone">Adding dependencies in the producer&#8217;s clone</a></li>
<li><a href="#_defining_stateful_http_contracts">Defining Stateful HTTP Contracts</a></li>
<li><a href="#_setting_up_the_spring_cloud_contract_plugin_on_the_producer_side">Setting up the Spring Cloud Contract plugin on the producer side</a></li>
<li><a href="#_turning_on_stub_runner_in_http_consumer_tests">Turning on Stub Runner in HTTP Consumer Tests</a></li>
<li><a href="#_producer_flow_1">Producer Flow 1</a>
<ul class="sectlevel3">
<li><a href="#_ide_setup_2">IDE setup</a></li>
<li><a href="#_setting_up_the_spring_cloud_contract_plugin">Setting up the Spring Cloud Contract plugin</a></li>
<li><a href="#_generating_tests_from_contracts">Generating Tests from Contracts</a></li>
<li><a href="#_fixing_broken_http_tests">Fixing Broken HTTP Tests</a></li>
</ul>
</li>
<li><a href="#_consumer_flow_2">Consumer flow 2</a></li>
<li><a href="#_generating_documentation_from_contracts">Generating documentation from contracts</a></li>
</ul>
</li>
<li><a href="#_solutions">Solutions</a>
<ul class="sectlevel2">
<li><a href="#_written_consumer_tests">Written consumer tests</a></li>
<li><a href="#_adding_spring_cloud_contract_dependency">Adding Spring Cloud Contract Dependency</a></li>
<li><a href="#_proposal_of_simple_contracts_by_consumer">Proposal of simple contracts by consumer</a></li>
<li><a href="#_missing_consumer_controller_code">Missing consumer controller code</a></li>
<li><a href="#_stub_logs">Stub Logs</a></li>
<li><a href="#_beer_request">Beer Request</a></li>
<li><a href="#_missing_listener_code">Missing listener code</a></li>
<li><a href="#_missing_triggers">Missing triggers</a></li>
<li><a href="#_messaging_dsls">Messaging DSLs</a></li>
<li><a href="#_producercontroller_implementation">ProducerController implementation</a></li>
<li><a href="#_beerrestbase">BeerRestBase</a></li>
<li><a href="#_beermessagingbase">BeerMessagingBase</a></li>
<li><a href="#_messaging_implementation">Messaging implementation</a></li>
<li><a href="#_scenario_contracts">Scenario contracts</a></li>
<li><a href="#_intoxication_controller">Intoxication Controller</a></li>
<li><a href="#_beerintoxicationbase">BeerIntoxicationBase</a></li>
</ul>
</li>
<li><a href="#_back_to_the_main_page">Back to the Main Page</a></li>
</ul>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>In this tutorial. we keep the contracts together with the producer code. In the
contracts, we describe a stateful scenario where the stub needs to have "memory" to know
what the previous state was and what the next one should be.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_scenarios">Scenarios</h2>
<div class="sectionbody">
<div class="imageblock">
<div class="content">
<img src="../images/scenario.png" alt="scenario">
</div>
<div class="title">Figure 1. Stateful scenario. The more you drink the more wasted you get</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_flow">Flow</h2>
<div class="sectionbody">
<div class="imageblock">
<div class="content">
<img src="../images/flow.png" alt="flow">
</div>
<div class="title">Figure 2. Consumer Driven Contract flow</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_tutorial">Tutorial</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Using Consumer Driven Contracts is like using TDD at the architecture level. We start by
writing a test on the consumer side.
=== Consumer flow 1</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../images/consumer_flow_1.png" alt="consumer flow 1">
</div>
<div class="title">Figure 3. Interact with cloned producer code</div>
</div>
<div class="sect3">
<h4 id="_ide_setup">IDE setup</h4>
<div class="paragraph">
<p>In your IDE, open the <code>consumer</code> project (through either Maven or Gradle).</p>
</div>
<div class="paragraph">
<p>In this scenario we need to write a test for HTTP communication that meets the following
criteria:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The consumer gets asked about the current and previous state of intoxication of a given
person.</p>
</li>
<li>
<p>The more you drink, the more intoxicated you get.</p>
</li>
<li>
<p>The flow of intoxication states goes <code>SOBER</code> &#8594; <code>TIPSY</code> &#8594; <code>DRUNK</code> &#8594; <code>WASTED</code>.</p>
</li>
<li>
<p>The consumer asks the producer for a beer for a given person and, in return the
information about the state of intoxication is sent back</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>In the standard CDC process, we would do TDD. However, in this case, you already have
some code ready. The test <code>IntoxicationControllerTest</code> contains tests of our feature.
In the <code>IntoxicationController</code>, we need to call an endpoint on the producer side.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s first write our missing test. There&#8217;s already a method called
<code>sendARequestAndExpectStatuses</code> created for us to fill out. We want to use <code>MockMvc</code> to
send a request to the <code>/wasted</code> endpoint with the name <code>marcin</code> in the JSON request body.
As a response, we expect to get the <code>previousStatus</code> and <code>currentStatus</code> of intoxication.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		this.mockMvc.perform(MockMvcRequestBuilders.post("/wasted")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin")).getJson()))
				.andExpect(status().isOk())
				.andExpect(content().json("{\"previousStatus\":\"" + previousStatus.name() +
						"\",\"currentStatus\":\"" + currentStatus.name() + "\"}"));</code></pre>
</div>
</div>
<div class="paragraph">
<p>If we run this test, it fails because we did not write an implementation in the
<code>IntoxicationController</code>. We want to write the implementation, but we do not yet know the
structure of the request. Since we do not yet know how the API should look, we can clone
the producer&#8217;s code to experiment with its API.</p>
</div>
</div>
<div class="sect3">
<h4 id="_cloning_the_producer_s_code">Cloning the producer&#8217;s code</h4>
<div class="ulist">
<ul>
<li>
<p>In this tutorial we will not clone the producer&#8217;s code, we&#8217;ll just open it in the IDE</p>
</li>
<li>
<p>There&#8217;s some production code written on the producer side but you could completely remove it. The idea
of CDC is that defining of contract can be done without writing a single line of code for the feature.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_adding_dependencies_in_the_producer_s_clone">Adding dependencies in the producer&#8217;s clone</h4>
<div class="ulist">
<ul>
<li>
<p>Since we want the IDE to help us with code completion, let&#8217;s add the necessary Spring Cloud Contract
dependencies. You need to add <code>spring-cloud-starter-contract-verifier</code> as a test dependency</p>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
	&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
	&lt;artifactId&gt;spring-cloud-starter-contract-verifier&lt;/artifactId&gt;
	&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testCompile("org.springframework.cloud:spring-cloud-starter-contract-verifier")</code></pre>
</div>
</div>
</li>
<li>
<p>This is a task that you would do once only since when you&#8217;ll be adding next contracts
all the dependencies will already be added</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_defining_stateful_http_contracts">Defining Stateful HTTP Contracts</h4>
<div class="paragraph">
<p>In the clone of the producer&#8217;s code, let&#8217;s create a folder called
<code>src/test/resources/contracts/beer/intoxication</code>. In Spring Cloud Contract, you can
define steps for a given scenario by relying on the naming convention of the files: If
your contract file starts with a number and a <code>_</code> character, it is assumed to be part of
the scenario. Here are three examples: <code>1_sober.groovy</code>, <code>2_tipsy.groovy</code>, and
<code>3_drunk.groovy</code>.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s create those three files and start writing our first scenario. Open the
<code>1_sober.groovy</code> file. We need to start by calling the
<code>org.springframework.cloud.contract.spec.Contract.make</code> method.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {

}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now let&#8217;s provide a meaningful description by using the <code>description</code> method, as shown in
the following code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
    Represents first step of getting fully drunk

    given:
        you didn't drink anything
    when:
        you get a beer
    then:
        you'll be tipsy
    """)
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Next we can define the <code>request</code> part of the contract, as shown in the following code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
    Represents first step of getting fully drunk

    given:
        you didn't drink anything
    when:
        you get a beer
    then:
        you'll be tipsy
    """)
    request {

    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Let&#8217;s assume that we want to send a <code>POST</code> request to to the <code>/beer</code> endpoint. To do so,
we might use the following code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
    Represents first step of getting fully drunk

    given:
        you didn't drink anything
    when:
        you get a beer
    then:
        you'll be tipsy
    """)
    request {
        method POST()
        url "/beer"
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The body should contain a <code>name</code> field equal to <code>marcin</code>. We can use the Groovy map
notation to define it, as shown in the following code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
    Represents first step of getting fully drunk

    given:
        you didn't drink anything
    when:
        you get a beer
    then:
        you'll be tipsy
    """)
    request {
        method POST()
        url "/beer"
        body(name: "marcin")
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The content type should be <code>application/json</code>. The following code shows how to set it:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
    Represents first step of getting fully drunk

    given:
        you didn't drink anything
    when:
        you get a beer
    then:
        you'll be tipsy
    """)
    request {
        method POST()
        url "/beer"
        body(name: "marcin")
        headers {
            contentType(applicationJson())
        }
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Congratulations! You successfully defined the request side of the contract. Let&#8217;s now
proceed with the response side, by defining the <code>response</code> block:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
    Represents first step of getting fully drunk

    given:
        you didn't drink anything
    when:
        you get a beer
    then:
        you'll be tipsy
    """)
    request {
        method POST()
        url "/beer"
        body(name: "marcin")
        headers {
            contentType(applicationJson())
        }
    }
    response {

    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>We want the response to return status <code>200</code>, which we can do with the following code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
    Represents first step of getting fully drunk

    given:
        you didn't drink anything
    when:
        you get a beer
    then:
        you'll be tipsy
    """)
    request {
        method POST()
        url "/beer"
        body(name: "marcin")
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The response body should return a value of <code>SOBER</code> in the the <code>previousStatus</code> field and
a value of <code>TIPSY</code> in the the <code>currentStatus</code> field. The following code shows how we
might do it:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
    Represents first step of getting fully drunk

    given:
        you didn't drink anything
    when:
        you get a beer
    then:
        you'll be tipsy
    """)
    request {
        method POST()
        url "/beer"
        body(name: "marcin")
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body(
            previousStatus: "SOBER",
            currentStatus: "TIPSY"
        )
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Finally, the response headers should contain a content type of <code>application/json</code>, as
shown in the following code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
Represents first step of getting fully drunk

given:
    you didn't drink anything
when:
    you get a beer
then:
    you'll be tipsy
""")
    request {
        method 'POST'
        url '/beer'
        body(
                name: "marcin"
        )
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body(
            previousStatus: "SOBER",
            currentStatus: "TIPSY"
        )
        headers {
            contentType(applicationJson())
        }
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Congratulations! You have successfully created your first contract!</p>
</div>
<div class="paragraph">
<p>Now we need to define the next two contracts: <code>2_tipsy.groovy</code> and <code>3_drunk.groovy</code>. You
can examine the <a href="#_scenario_contracts">solution</a>. The first transition will be from
<code>TIPSY</code> &#8594; <code>DRUNK</code>. The last transition will be from <code>DRUNK</code> &#8594; <code>WASTED</code>.</p>
</div>
<div class="paragraph">
<p>We have managed to define all the scenarios. Now we would like to generate the stubs so
that we can reuse them on the consumer side. To that end, we must set up the Spring Cloud
Contract plugin in the cloned repository, as shown in the following code:</p>
</div>
</div>
<div class="sect3">
<h4 id="_setting_up_the_spring_cloud_contract_plugin_on_the_producer_side">Setting up the Spring Cloud Contract plugin on the producer side</h4>
<div class="ulist">
<ul>
<li>
<p>Ok, at this moment we&#8217;ve described the API that would be interesting for us, consumers, and most likely
will suit our needs. We define those contracts cause we want to have some stubs produced for us without
needing to write a single line of the implementation code. The tool that we need to do this conversion
is the Spring Cloud Contract plugin. Let&#8217;s add it to the producer&#8217;s <code>pom.xml</code> / <code>build.gradle</code>.</p>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;plugin&gt;
    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-contract-maven-plugin&lt;/artifactId&gt;
    &lt;version&gt;${spring-cloud-contract.version}&lt;/version&gt;
    &lt;extensions&gt;true&lt;/extensions&gt;
&lt;/plugin&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">buildscript {
	dependencies {
		classpath "org.springframework.cloud:spring-cloud-contract-gradle-plugin:${verifierVersion}"
	}
}</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>The coordinates of the plugin are: <code>org.springframework.cloud:spring-cloud-contract-gradle-plugin:$2.1.3.BUILD-SNAPSHOT</code></p>
</li>
<li>
<p>For this tutorial we&#8217;re using latest snapshot versions that you can reference via the Maven&#8217;s
<code>${spring-cloud-contract.version}</code> property or Gradle&#8217;s <code>verifierVersion</code> one</p>
</li>
<li>
<p>Once the plugin has been added just call the commands to install the stubs locally</p>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./mvnw clean install -DskipTests</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./gradlew clean build publishToMavenLocal -x test</code></pre>
</div>
</div>
</li>
<li>
<p>Now you can check out <code>target/stubs/META-INF/com.example/beer-api-producer/0.0.1-SNAPSHOT</code> for Maven or
<code>build/stubs/META-INF/com.example/beer-api-producer/0.0.1-SNAPSHOT</code> for Gradle. Over there you&#8217;ll see
<code>contracts</code> folder where all contracts got copied and the <code>mappings</code> folder where you&#8217;ll find all the
generated stubs. By default Spring Cloud Contract uses <a href="http://wiremock.org">WireMock</a> as an implementation
of fake HTTP server. Under the <code>rest</code> subfolder you&#8217;ll see all the generated stubs. Notice that
we&#8217;re using JSON Paths to check the contents of the request.</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>If you check out the <code>1_sober.json</code> intoxication stub, you can see the following section:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-json" data-lang="json">"scenarioName" : "Scenario_intoxication",
"requiredScenarioState" : "Started",
"newScenarioState" : "Step1"</code></pre>
</div>
</div>
<div class="paragraph">
<p>In this section, WireMock is told that:
* The name of the scenario is <code>Scenario_intoxication</code>. The name comes from the folder in
which the contracts were placed.
* The required scenario state is <code>Started</code>. That&#8217;s the initial state.
* The next step is <code>Step1</code>. Every subsequent step will be called <code>Step</code> with appropriate
number appended.</p>
</div>
<div class="paragraph">
<p>If you check out <code>2_tipsy.json</code>, you can see that the required values of the previous and
next states got updated:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-json" data-lang="json">"scenarioName" : "Scenario_intoxication",
"requiredScenarioState" : "Step1",
"newScenarioState" : "Step2"</code></pre>
</div>
</div>
<div class="paragraph">
<p>We have managed to install the stubs locally. it&#8217;s time to move back to our consumer
test. Let&#8217;s open the <code>IntoxicationController</code> class and write the missing implementation.
You can try to write it yourself or check out the <a href="#_intoxication_controller">solution</a>.</p>
</div>
</div>
<div class="sect3">
<h4 id="_turning_on_stub_runner_in_http_consumer_tests">Turning on Stub Runner in HTTP Consumer Tests</h4>
<div class="paragraph">
<p>After writing the implementation, if we rerun the tests, we get a connection refused
exception. That happens because we have yet to start the HTTP server with the stubs, as
we do in the following snippet:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Now it&#8217;s time to turn on the magic! Let&#8217;s add the Spring Cloud Starter Contract Stub Runner test dependency.</p>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
	&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
	&lt;artifactId&gt;spring-cloud-starter-contract-stub-runner&lt;/artifactId&gt;
	&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testCompile("org.springframework.cloud:spring-cloud-starter-contract-stub-runner")</code></pre>
</div>
</div>
</li>
<li>
<p>We can annotate our test class with
<code>@AutoConfigureStubRunner(stubsMode = StubRunnerProperties.StubsMode.LOCAL, ids = "com.example:beer-api-producer:+:stubs:8090")</code>. What that
will do is:</p>
<div class="ulist">
<ul>
<li>
<p>it will download the stub JARs from Maven local (<code>stubsMode = StubRunnerProperties.StubsMode.LOCAL</code>)</p>
</li>
<li>
<p>it will search for a JAR with coordinates <code>com.example:beer-api-producer</code> with latest version (<code>+</code>)
and <code>stubs</code> classifier. Once it&#8217;s found the fake HTTP server stub will be started at port <code>8090</code></p>
</li>
</ul>
</div>
</li>
<li>
<p>Rerun the test - it should automagically pass!</p>
<div class="ulist">
<ul>
<li>
<p>In the logs you will see information about downloading, unpacking and starting stubs (<a href="#_stub_logs">see the logs</a>)</p>
</li>
<li>
<p>What happened is that we could interact with real API without writing a single line of production code</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>Congratulations! You have successfully created the contracts, defined the API that suits
your needs, and written the consumer part of the functionality! Now it&#8217;s time to create a
pull request with the contract proposal and file it to the producer side.</p>
</div>
</div>
<div class="sect2">
<h3 id="_producer_flow_1">Producer Flow 1</h3>
<div class="imageblock">
<div class="content">
<img src="../images/producer_flow_1.png" alt="producer flow 1">
</div>
<div class="title">Figure 4. Producer takes over the PR, writes missing impl and merges the PR</div>
</div>
<div class="sect3">
<h4 id="_ide_setup_2">IDE setup</h4>
<div class="ulist">
<ul>
<li>
<p>Open in your IDE the <code>producer</code> project (either via Maven or Gradle)</p>
</li>
<li>
<p>We&#8217;re assuming that we&#8217;ve taken over the PR. Example of how to achieve that in "real life" for a PR
that got submitted to via a branch called <code>the_pr</code> looks like this:</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">git fetch origin
git checkout -b the_pr origin/the_pr
git merge master</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>The idea of Spring Cloud Contract is about stub and contract validity. Right now we have a set of
contracts defined but we haven&#8217;t tested it against the producer side. Time to change that!</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_setting_up_the_spring_cloud_contract_plugin">Setting up the Spring Cloud Contract plugin</h4>
<div class="ulist">
<ul>
<li>
<p>Spring Cloud Contract can generate tests from your contracts to ensure that your implementation&#8217;s API
is compatible with the defined contract. Let&#8217;s set up the project to start generating tests.</p>
<div class="ulist">
<ul>
<li>
<p>Spring Cloud Contract needs a base class that all of the generated tests will extend. Currently
we support 3 different ways of defining a base class (you can read more about this in the
Spring Cloud Contract documentation for <a href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_configure_plugin">Gradle</a>
and <a href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_configure_plugin_2">Maven</a>)</p>
<div class="ulist">
<ul>
<li>
<p>a single class for all tests</p>
</li>
<li>
<p>convention based naming (takes 2 last package names and appends <code>Base</code>. Having a contract
<code>src/test/resources/contracts/foo/bar/shouldDoSth.groovy</code> would create a test class called
<code>BarTest</code> that would extend <code>FooBarBase</code> class.</p>
</li>
<li>
<p>manual mapping (you can state that contracts matching certain regular expression will have to
have a base class with fully qualified name equal to X)</p>
</li>
</ul>
</div>
</li>
<li>
<p>In the following example we&#8217;ll play with convention based naming</p>
<div class="ulist">
<ul>
<li>
<p>For Maven under the plugin setup you have to set up the plugin configuration
<code>&lt;configuration&gt;&lt;packageWithBaseClasses&gt;com.example&lt;/packageWithBaseClasses&gt;&lt;/configuration&gt;</code></p>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;plugin&gt;
    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-contract-maven-plugin&lt;/artifactId&gt;
    &lt;version&gt;${spring-cloud-contract.version}&lt;/version&gt;
    &lt;extensions&gt;true&lt;/extensions&gt;
    &lt;configuration&gt;
        &lt;packageWithBaseClasses&gt;com.example&lt;/packageWithBaseClasses&gt;
    &lt;/configuration&gt;
&lt;/plugin&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">contracts {
    packageWithBaseClasses = 'com.example'
}</code></pre>
</div>
</div>
</li>
<li>
<p>In both cases passing of that value tells the plugin that a given base class is available under
the <code>com.example</code> package</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
We were setting the plugin in the following since most likely you use the same
<code>producer</code> codebase as you have for previous tutorials. That is why we want the other
tests to still pass. If that&#8217;s not the case (if you have only just started with this
particular tutorial) then you can remove the <code>packageWithBaseClasses</code> entry.
</td>
</tr>
</table>
</div>
<div class="ulist">
<ul>
<li>
<p>The intoxication base class lays under the <code>intoxication</code> folder. Let&#8217;s use the
<code>baseClassMappings</code> to set point the plugin to proper base classes, as shown in the
following snippet (for both Maven and Gradle):</p>
</li>
</ul>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;plugin&gt;
    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-contract-maven-plugin&lt;/artifactId&gt;
    &lt;version&gt;${spring-cloud-contract.version}&lt;/version&gt;
    &lt;extensions&gt;true&lt;/extensions&gt;
    &lt;configuration&gt;
        &lt;packageWithBaseClasses&gt;com.example&lt;/packageWithBaseClasses&gt;
        &lt;baseClassMappings&gt;
            &lt;baseClassMapping&gt;
                &lt;contractPackageRegex&gt;.*intoxication.*&lt;/contractPackageRegex&gt;
                &lt;baseClassFQN&gt;com.example.intoxication.BeerIntoxicationBase&lt;/baseClassFQN&gt;
            &lt;/baseClassMapping&gt;
        &lt;/baseClassMappings&gt;
    &lt;/configuration&gt;
&lt;/plugin&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">contracts {
	packageWithBaseClasses = 'com.example'
	baseClassMappings {
		baseClassMapping(".*intoxication.*", "com.example.intoxication.BeerIntoxicationBase")
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_generating_tests_from_contracts">Generating Tests from Contracts</h4>
<div class="paragraph">
<p>Let&#8217;s generate the tests! To do so, use the following code (for both Maven and Gradle):</p>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./mvnw clean install</code></pre>
</div>
</div>
<div class="paragraph">
<p>+</p>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./gradlew clean build publishToMavenLocal</code></pre>
</div>
</div>
<div class="paragraph">
<p>Consider a situation in which, suddenly, some tests start failing. Those tests are the
autogenerated tests created by Spring Cloud Contract. The tests can be found under
<code>/generated-test-sources/contracts/org/springframework/cloud/contract/verifier/tests/beer</code>,
in the <code>target</code> directory for Maven and in the <code>build</code> directory for Gradle. There is a
test for each folder in which you store your contracts. The name of the test
class is the name of that folder. Each of the contracts is a single test inside that test
class. If you check out the generated <code>IntoxicationTest</code>, you can seee that it got
annotated with <code>@FixMethodOrder(MethodSorters.NAME_ASCENDING)</code> in order to ensure
that the tests are executed sequentially.</p>
</div>
<div class="paragraph">
<p>Now we can fix the broken tests by providing the missing implementation.</p>
</div>
</div>
<div class="sect3">
<h4 id="_fixing_broken_http_tests">Fixing Broken HTTP Tests</h4>
<div class="paragraph">
<p>Let&#8217;s start with HTTP. First, let&#8217;s write the missing implementation in
<code>BeerServingController</code>. The logic to be written is simple: The
<code>responseProvider.thereYouGo(&#8230;&#8203;)</code> returns the <code>Response</code>. The implementation is
basically a one liner, as shown in the following code snippet:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">return this.responseProvider.thereYouGo(customer);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Let&#8217;s fix the <code>BeerIntoxicationBase</code> class now. The idea of CDC is <strong>NOT TO TEST</strong> every
single feature. Contract tests are there to see if the API is matched, <strong>NOT</strong> to test that
the feature is working. That&#8217;s why we shouldn&#8217;t be accessing databases and taking similar
actions. That means that we can work with a fake instance of the <code>ResponseProvider</code>.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s start by writing the missing implementation of the <code>MockResponseProvider</code>
(<a href="#_beerintoxicationbase">Show solution</a>). You need to:
* ensure that the <code>name</code> is equal to <code>marcin</code>
* depending on the <code>current</code> state you&#8217;ll need to set the <code>previous</code> and
<code>current</code> one and create the <code>Response</code>.</p>
</div>
<div class="paragraph">
<p>We need to maintain state between the tests. If you try to store the state in a field in
a base class, you lose it between test executions, because JUnit is reinitializing all
the fields. We can fix that by setting up a small Spring Context to be reused. The
following example shows what that annotation might look like:</p>
</div>
<div class="paragraph">
<p>+</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@SpringBootTest(classes = BeerIntoxicationBase.Config.class)</code></pre>
</div>
</div>
<div class="paragraph">
<p>We want RestAssured and MockMvc to reuse the web context that we have in our test. That&#8217;s
why we need to set it up by using the following notation:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">    @Autowired WebApplicationContext webApplicationContext;

    @Before
    public void setup() {
        RestAssuredMockMvc.webAppContextSetup(webApplicationContext);
    }</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now, when try re-running the build to regenerate the tests, the tests should pass. You
could now merge the pull request to master, and your CI system would build a fat jar and
the stubs.</p>
</div>
<div class="paragraph">
<p>Congratulations! You have completed the producer side of this tutorial!</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_consumer_flow_2">Consumer flow 2</h3>
<div class="imageblock">
<div class="content">
<img src="../images/consumer_flow_2.png" alt="consumer flow 2">
</div>
<div class="title">Figure 5. Switch to work online</div>
</div>
<div class="ulist">
<ul>
<li>
<p>After merging the PR the producer&#8217;s stubs reside in some Artifactory / Nexus instance</p>
</li>
<li>
<p>As consumers we no longer want to retrieve the stubs from our local Maven repository -
we&#8217;d like to download them from the remote location</p>
</li>
<li>
<p>To do that (we won&#8217;t do that for the tutorial but you would do it in your "production"
code) it&#8217;s enough to pass the <code>repositoryRoot</code> parameter and set the
<code>stubsMode</code> to <code>StubRunnerProperties.StubsMode.REMOTE</code></p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
@AutoConfigureMockMvc
@AutoConfigureJsonTesters
@AutoConfigureStubRunner(
repositoryRoot="http://www.foo.com/bar,
ids = "com.example:beer-api-producer:+:stubs:8090",
stubsMode = StubRunnerProperties.StubsMode.REMOTE
)
@DirtiesContext
public class YourTestOnTheConsumerSide extends AbstractTest {
}</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Another option is to pass the property <code>stubrunner.repositoryRoot</code> either as a
system / environment property, or via an <code>application.yml</code> and <code>stubrunner.stubs-mode</code>
equal to <code>remote</code></p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_generating_documentation_from_contracts">Generating documentation from contracts</h3>
<div class="paragraph">
<p>Another feature of Spring Cloud Contract is an option to easily create the documentation
of the whole API of the producer. You can create the following test that will generate a
<code>contracts.adoc</code> file under <code>target/generated-snippets/</code> with description of contracts and
with the contract bodies as such.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
This test is a poor man&#8217;s version of the documentation generation. You can customize
it as you wish - the current version is just to show you an example.
</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">package docs;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.contract.spec.Contract;
import org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter;
import org.springframework.core.io.Resource;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collection;
import java.util.regex.Pattern;

@RunWith(SpringRunner.class)
public class GenerateAdocsFromContractsTests {

	// TODO: Can be parametrized
	@Value("classpath:contracts") Resource contracts;
	private static String header = "= Application Contracts\n" + "\n"
			+ "In the following document you'll be able to see all the contracts that are present for this application.\n"
			+ "\n" + "== Contracts\n";

	@Test public void should_convert_contracts_into_adoc() throws IOException {
		final StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append(header);
		final Path rootDir = this.contracts.getFile().toPath();

		Files.walkFileTree(rootDir, new FileVisitor&lt;Path&gt;() {
			private Pattern pattern = Pattern.compile("^.*groovy$");

			@Override
			public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes atts)
					throws IOException {
				return FileVisitResult.CONTINUE;
			}

			@Override
			public FileVisitResult visitFile(Path path, BasicFileAttributes mainAtts)
					throws IOException {
				boolean matches = this.pattern.matcher(path.toString()).matches();
				if (matches) {
					appendContract(stringBuilder, path);
				}
				return FileVisitResult.CONTINUE;
			}

			@Override
			public FileVisitResult postVisitDirectory(Path path, IOException exc)
					throws IOException {
				return FileVisitResult.CONTINUE;
			}

			@Override public FileVisitResult visitFileFailed(Path path, IOException exc)
					throws IOException {
				// If the root directory has failed it makes no sense to continue
				return path.equals(rootDir) ?
						FileVisitResult.TERMINATE :
						FileVisitResult.CONTINUE;
			}
		});

		//String outputAdoc = asciidoctor.convert(stringBuilder.toString(), new HashMap&lt;String, Object&gt;());
		String outputAdoc = stringBuilder.toString();
		// TODO: Can be parametrized
		File outputDir = new File("target/generated-snippets");
		outputDir.mkdirs();
		// TODO: Can be parametrized
		File outputFile = new File(outputDir, "contracts.adoc");
		if (outputFile.exists()) {
			outputFile.delete();
		}
		if (outputFile.createNewFile()) {
			Files.write(outputFile.toPath(), outputAdoc.getBytes());
		}
	}

	static StringBuilder appendContract(final StringBuilder stringBuilder, Path path)
			throws IOException {
		Collection&lt;Contract&gt; contracts = ContractVerifierDslConverter.convertAsCollection(path.getParent().toFile(), path.toFile());
		// TODO: Can be parametrized
		contracts.forEach(contract -&gt; {
			stringBuilder.append("### ")
					.append(path.getFileName().toString())
					.append("\n\n")
					.append(contract.getDescription())
					.append("\n\n")
					.append("#### Contract structure")
					.append("\n\n")
					.append("[source,java,indent=0]")
					.append("\n")
					.append("----")
					.append("\n")
					.append(fileAsString(path))
					.append("\n")
					.append("----")
					.append("\n\n");
		});
		return stringBuilder;
	}

	static String fileAsString(Path path) {
		try {
			byte[] encoded = Files.readAllBytes(path);
			return new String(encoded, StandardCharsets.UTF_8);
		}
		catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_solutions">Solutions</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_written_consumer_tests">Written consumer tests</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	@Test
	public void should_give_me_a_beer_when_im_old_enough() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/beer")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin", 22)).getJson()))
				.andExpect(status().isOk())
				.andExpect(content().string("THERE YOU GO"));
		//remove::end[]
	}

	@Test
	public void should_reject_a_beer_when_im_too_young() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/beer")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin", 17)).getJson()))
				.andExpect(status().isOk())
				.andExpect(content().string("GET LOST"));
		//remove::end[]
	}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_adding_spring_cloud_contract_dependency">Adding Spring Cloud Contract Dependency</h3>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
	&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
	&lt;artifactId&gt;spring-cloud-starter-contract-verifier&lt;/artifactId&gt;
	&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testCompile("org.springframework.cloud:spring-cloud-starter-contract-verifier")</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_proposal_of_simple_contracts_by_consumer">Proposal of simple contracts by consumer</h3>
<div class="paragraph">
<p><strong>HTTP communication</strong></p>
</div>
<div class="listingblock primary">
<div class="title">Old Enough</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// rest/shouldGrantABeerIfOldEnough.groovy
org.springframework.cloud.contract.spec.Contract.make {
		description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```

""")
	request {
		method 'POST'
		url '/check'
		body(
				age: 22,
				name: "marcin"
		)
		headers {
			contentType(applicationJson())
		}
	}
	response {
		status 200
		body("""
			{
				"status": "OK"
			}
			""")
		headers {
			contentType(applicationJson())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Too Young</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// rest/shouldRejectABeerIfTooYoung.groovy
org.springframework.cloud.contract.spec.Contract.make {
		description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```

""")
	request {
		method 'POST'
		url '/check'
		body(
				age: 17,
				name: "marcin"
		)
		headers {
			contentType(applicationJson())
		}
	}
	response {
		status 200
		body("""
			{
				"status": "NOT_OK"
			}
			""")
		headers {
			contentType(applicationJson())
		}
	}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Messaging communication</strong></p>
</div>
<div class="listingblock primary">
<div class="title">Positive Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendAcceptedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a positive verification message when person is eligible to get the beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll send a message with a positive verification
```

""")
	// Label by means of which the output message can be triggered
	label 'accepted_verification'
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: true
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Negative Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendRejectedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a negative verification message when person is not eligible to get the beer

```
given:
	client is too young
when:
	he applies for a beer
then:
	we'll send a message with a negative verification
```

""")
	// Label by means of which the output message can be triggered
	label 'rejected_verification'
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: false
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_consumer_controller_code">Missing consumer controller code</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		ResponseEntity&lt;Response&gt; response = this.restTemplate.exchange(
				RequestEntity
						.post(URI.create("http://localhost:" + this.port + "/check"))
						.contentType(MediaType.APPLICATION_JSON)
						.body(person),
				Response.class);
		switch (response.getBody().status) {
		case OK:
			return "THERE YOU GO";
		default:
			return "GET LOST";
		}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_stub_logs">Stub Logs</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">2017-05-11 12:16:51.146  INFO 4693 --- [           main] o.s.c.c.s.StubDownloaderBuilderProvider  : Will download stubs using Aether
2017-05-11 12:16:51.148  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Remote repos not passed but the switch to work offline was set. Stubs will be used from your local Maven repository.
2017-05-11 12:16:51.291  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Desired version is [+] - will try to resolve the latest version
2017-05-11 12:16:51.308  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved version is [0.0.1-SNAPSHOT]
2017-05-11 12:16:51.309  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolving artifact [com.example:{producer_artifact}:jar:stubs:0.0.1-SNAPSHOT] using remote repositories []
2017-05-11 12:16:51.317  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved artifact [com.example:{producer_artifact}:jar:stubs:0.0.1-SNAPSHOT] to /home/marcin/.m2/repository/com/example/{producer_artifact}/0.0.1-SNAPSHOT/{producer_artifact}-0.0.1-SNAPSHOT-stubs.jar
2017-05-11 12:16:51.322  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Unpacking stub from JAR [URI: file:/home/marcin/.m2/repository/com/example/{producer_artifact}/0.0.1-SNAPSHOT/{producer_artifact}-0.0.1-SNAPSHOT-stubs.jar]
2017-05-11 12:16:51.327  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Unpacked file to [/tmp/contracts9053257535983128167]
2017-05-11 12:16:52.608  INFO 4693 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@699e0bf0: startup date [Thu May 11 12:16:52 CEST 2017]; root of context hierarchy
2017-05-11 12:16:52.684  INFO 4693 --- [           main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2017-05-11 12:16:52.837  INFO 4693 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8090 (http)
2017-05-11 12:16:52.851  INFO 4693 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2017-05-11 12:16:52.853  INFO 4693 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.14
2017-05-11 12:16:52.975  INFO 4693 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-05-11 12:16:52.975  INFO 4693 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 367 ms
2017-05-11 12:16:52.996  INFO 4693 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'stub' to [/]
2017-05-11 12:16:53.000  INFO 4693 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'admin' to [/__admin/*]
2017-05-11 12:16:53.135  INFO 4693 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8090 (http)
2017-05-11 12:16:53.139  INFO 4693 --- [           main] o.s.c.contract.stubrunner.StubServer     : Started stub server for project [com.example:{producer_artifact}:0.0.1-SNAPSHOT:stubs] on port 8090</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beer_request">Beer Request</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">class BeerRequest {
	public int age;

	public BeerRequest(int age) {
		this.age = age;
	}

	public BeerRequest() {
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_listener_code">Missing listener code</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		if (verification.eligible) {
			this.eligibleCounter.incrementAndGet();
		} else {
			this.notEligibleCounter.incrementAndGet();
		}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_triggers">Missing triggers</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	@Test public void should_increase_the_eligible_counter_when_verification_was_accepted() throws Exception {
		int initialCounter = this.listener.eligibleCounter.get();

		//remove::start[]
		this.stubTrigger.trigger("accepted_verification");
		//remove::end[]

		then(this.listener.eligibleCounter.get()).isGreaterThan(initialCounter);
	}

	@Test public void should_increase_the_noteligible_counter_when_verification_was_rejected() throws Exception {
		int initialCounter = this.listener.notEligibleCounter.get();

		//remove::start[]
		this.stubTrigger.trigger("rejected_verification");
		//remove::end[]

		then(this.listener.notEligibleCounter.get()).isGreaterThan(initialCounter);
	}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_messaging_dsls">Messaging DSLs</h3>
<div class="listingblock primary">
<div class="title">Positive Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendAcceptedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a positive verification message when person is eligible to get the beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll send a message with a positive verification
```

""")
	// Label by means of which the output message can be triggered
	label 'accepted_verification'
	// input to the contract
	input {
		// the contract will be triggered by a method
		triggeredBy('clientIsOldEnough()')
	}
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: true
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Negative Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendRejectedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a negative verification message when person is not eligible to get the beer

```
given:
	client is too young
when:
	he applies for a beer
then:
	we'll send a message with a negative verification
```

""")
	// Label by means of which the output message can be triggered
	label 'rejected_verification'
	// input to the contract
	input {
		// the contract will be triggered by a method
		triggeredBy('clientIsTooYoung()')
	}
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: false
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_producercontroller_implementation">ProducerController implementation</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">if (personCheckingService.shouldGetBeer(personToCheck)) {
    return new Response(BeerCheckStatus.OK);
}
return new Response(BeerCheckStatus.NOT_OK);</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beerrestbase">BeerRestBase</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(MockitoJUnitRunner.class)
public abstract class BeerRestBase {
	@Mock PersonCheckingService personCheckingService;
	@InjectMocks ProducerController producerController;

	@Before
	public void setup() {
		given(personCheckingService.shouldGetBeer(argThat(oldEnough()))).willReturn(true);
		RestAssuredMockMvc.standaloneSetup(producerController);
	}

	private TypeSafeMatcher&lt;PersonToCheck&gt; oldEnough() {
		return new TypeSafeMatcher&lt;PersonToCheck&gt;() {
			@Override protected boolean matchesSafely(PersonToCheck personToCheck) {
				return personToCheck.age &gt;= 20;
			}

			@Override public void describeTo(Description description) {

			}
		};
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beermessagingbase">BeerMessagingBase</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@AutoConfigureMessageVerifier
public abstract class BeerMessagingBase {
	@Inject MessageVerifier messaging;
	@Autowired PersonCheckingService personCheckingService;

	@Before
	public void setup() {
		// let's clear any remaining messages
		// output == destination or channel name
		this.messaging.receive("output", 100, TimeUnit.MILLISECONDS);
	}

	public void clientIsOldEnough() {
		personCheckingService.shouldGetBeer(new PersonToCheck(25));
	}

	public void clientIsTooYoung() {
		personCheckingService.shouldGetBeer(new PersonToCheck(5));
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_messaging_implementation">Messaging implementation</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		boolean shouldGetBeer = personToCheck.age &gt;= 20;
		this.source.output().send(MessageBuilder.withPayload(new Verification(shouldGetBeer)).build());
		return shouldGetBeer;</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_scenario_contracts">Scenario contracts</h3>
<div class="listingblock primary">
<div class="title">Tipsy</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">package contracts.beer.intoxication

import org.springframework.cloud.contract.spec.Contract

Contract.make {
	description("""
Represents second step of getting fully drunk

given:
	you were tipsy
when:
	you get a beer
then:
	you'll be drunk
""")
	request {
		method 'POST'
		url '/beer'
		body(
				name: "marcin"
		)
		headers {
			contentType(applicationJson())
		}
	}
	response {
		status 200
		body(
				previousStatus: "TIPSY",
				currentStatus: "DRUNK"
		)
		headers {
			contentType(applicationJson())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Drunk</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">package contracts.beer.intoxication

import org.springframework.cloud.contract.spec.Contract

Contract.make {
	description("""
Represents last step of getting fully drunk

given:
	you were drunk
when:
	you get a beer
then:
	you'll be wasted
""")
	request {
		method 'POST'
		url '/beer'
		body(
				name: "marcin"
		)
		headers {
			contentType(applicationJson())
		}
	}
	response {
		status 200
		body(
				previousStatus: "DRUNK",
				currentStatus: "WASTED"
		)
		headers {
			contentType(applicationJson())
		}
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_intoxication_controller">Intoxication Controller</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">package com.example.intoxication;

import java.net.MalformedURLException;
import java.net.URI;

import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @author Marcin Grzejszczak
 */
@RestController
class IntoxicationController {

	private final RestTemplate restTemplate;

	int port = 8090;

	IntoxicationController(RestTemplate restTemplate) {
		this.restTemplate = restTemplate;
	}

	@RequestMapping(method = RequestMethod.POST,
			value = "/wasted",
			consumes = MediaType.APPLICATION_JSON_VALUE,
			produces = MediaType.APPLICATION_JSON_VALUE)
	public Response gimmeABeer(@RequestBody Person person) throws MalformedURLException {
		//remove::start[]
		return this.restTemplate.exchange(
				RequestEntity
						.post(URI.create("http://localhost:" + this.port + "/beer"))
						.contentType(MediaType.APPLICATION_JSON)
						.body(person),
				Response.class).getBody();
		//remove::end[return]
	}
}

class Person {
	public String name;

	public Person(String name) {
		this.name = name;
	}

	public Person() {
	}
}

class Response {
	public DrunkLevel previousStatus;
	public DrunkLevel currentStatus;

	public Response(DrunkLevel previousStatus, DrunkLevel currentStatus) {
		this.previousStatus = previousStatus;
		this.currentStatus = currentStatus;
	}

	public Response() {
	}
}

enum DrunkLevel {
	SOBER, TIPSY, DRUNK, WASTED
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beerintoxicationbase">BeerIntoxicationBase</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">package com.example.intoxication;

//remove::start[]
import io.restassured.module.mockmvc.RestAssuredMockMvc;
//remove::end[]

import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.context.WebApplicationContext;

import static com.example.intoxication.DrunkLevel.DRUNK;
import static com.example.intoxication.DrunkLevel.SOBER;
import static com.example.intoxication.DrunkLevel.TIPSY;
import static com.example.intoxication.DrunkLevel.WASTED;

/**
 * Tests for the scenario based stub
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = BeerIntoxicationBase.Config.class)
public abstract class BeerIntoxicationBase {

	@Autowired WebApplicationContext webApplicationContext;

	@Before
	public void setup() {
		//remove::start[]
		RestAssuredMockMvc.webAppContextSetup(this.webApplicationContext);
		//remove::end[]
	}

	@Configuration
	@EnableAutoConfiguration
	static class Config {

		@Bean BeerServingController controller() {
			return new BeerServingController(responseProvider());
		}

		@Bean ResponseProvider responseProvider() {
			return new MockResponseProvider();
		}
	}

	//tag::mock[]
	static class MockResponseProvider implements ResponseProvider {

		private DrunkLevel previous = SOBER;
		private DrunkLevel current = SOBER;

		@Override public Response thereYouGo(Customer personToCheck) {
			//remove::start[]
			if ("marcin".equals(personToCheck.name)) {
				 switch (this.current) {
				 case SOBER:
					 this.current = TIPSY;
					 this.previous = SOBER;
					 break;
				 case TIPSY:
					 this.current = DRUNK;
					 this.previous = TIPSY;
					 break;
				 case DRUNK:
					 this.current = WASTED;
					 this.previous = DRUNK;
					 break;
				 case WASTED:
					 throw new UnsupportedOperationException("You can't handle it");
				 }
			}
			//remove::end[]
			return new Response(this.previous, this.current);
		}
	}
	//end::mock[]
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_back_to_the_main_page">Back to the Main Page</h2>
<div class="sectionbody">
<div class="paragraph">
<p><a href="../workshops.html">Click here to go back to the main page</a></p>
</div>
</div>
</div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js"></script>
<script>prettyPrint()</script>
</body>
</html>